import numpy as np
from PyQt4 import QtCore
import sys,os,inspect
sys.path.insert(0,os.path.abspath(os.path.join(os.getcwd(), os.pardir)))## add root path 
from KModel.KSingleStock import KSingleStock
from KModel.KSingleStockDataProcessor import KSingleStockDataProcessor as kprocesser
from KModel.KSingleStockCursor import KSingleStockCursor 
from KTrade.KStockFeed import KStockFeed
from KTrade.KBaseStrategy import KBaseStrategy
from KIndicators.K_MA import K_MA
from KIndicators.KGartelyHighProb import KGartelyHighProb
from KTrade.KHolding import KHolding
from KTrade.KStrategyMetric.KBaseMetric import *
import matplotlib.pyplot as plt
import importlib
import KTrade.KStrategyMetric.KBaseMetric
import cProfile	
import pstats
class KStrategyCMiner(KBaseStrategy):
	def __init__(self,parent,stockfeed):
		super(KStrategyCMiner,self).__init__(parent,stockfeed)
		
		self.waveindicator=KGartelyHighProb(self.stockfeed.GetStockSymbol())
		#self.waveindicator.calculate()


		
	def OnStart(self):
		# called before test started
		print('starting cMiner strategy')
		self.waveindicator.SetupStockFeed(self.stockfeed)
		self.waveindicator.OnStart()
		'''patterncount: patterns generated till now.
		curpattern: latest pattern considered.
		stoploss: stop loss price
		cpoint: potential cpoint we predicted
		stopwin: # targeted stop win price
		'''
		self.tradedict={'patterncount':0,'curpattern':None,'stoploss':None,'cpoint':None,'stopwin':None}
		
	def OnFinish(self):
		# call after test exectued
		print('finishing cMiner strategy')
		self.waveindicator.OnFinish()

		
	def OnNewBars(self,curfeedindex):
		# called whenever new bar is generated	

		# call base class method, must be called as a first step in this method		
		KBaseStrategy.OnNewBars(self,curfeedindex)
		self.waveindicator.OnNewBars(curfeedindex)
		
		# get current close price
		closep=self.stockfeed.GetBarByIndex(curfeedindex,'close')
		symbol=self.stockfeed.GetSymbolName()
		[sharsnum,curtype]=self.position.GetHoldingCountAndType(symbol)		

		# no holding now, seeking enter long opportunity
		if curtype!=KHolding.HoldType.LONG:	
			
			# detect chance to enter long
			patterns=self.waveindicator.GetPatternList()
			self.UpdateCurrentPattern()
			if self.tradedict['curpattern']:
				if self.IsEnterLongOpportunity(closep):
					self.TryToEnterLong(closep)
					
		# have holding now, seeking exit long opportunity
		else: 
			
			# update stop loss price
			
			if closep>self.tradedict['stopwin']:
				self.tradedict['stoploss']=closep*0.95 # raise stop loss price if reached target profit price
				
															   
			# detect chance to exit long
			if self.IsExitLongOpportunity(closep):
				self.TryToExitLong(closep)
		

	def ErasePattern(self):
		# erase current tracked pattern since the pattern become invalidate or the position exit.
		self.tradedict['curpattern']=None
		self.tradedict['stoploss']=None
		self.tradedict['cpoint']=None
		self.tradedict['stopwin']=None		
		
	def UpdateCurrentPattern(self):
		# keep track of lasted pattern
		
		patterns=self.waveindicator.GetPatternList()
		if len(patterns)>self.tradedict['patterncount']:
			# new pattern detected, record it
			self.tradedict['patterncount']=len(patterns)
			self.tradedict['curpattern']=patterns[-1]	
			
	def IsExitLongOpportunity(self,closep):
		
		# detect whether need to exit
		symbol=self.stockfeed.GetSymbolName()	
		if self.tradedict['stoploss']:  
			# print('proection %.2f, current price %.2f'%(self.stoploss,closep))
			if self.tradedict['stoploss']>=closep: # fall bellow close price, need to exit
				return True
		return False

		
	def TryToExitLong(self,closep):
		
		symbol=self.stockfeed.GetSymbolName()
		[sharsnum,curtype]=self.position.GetHoldingCountAndType(symbol)
		if self.position.ExitLong(symbol,closep,sharsnum):
			print('sell %d of shares at %.2f$' %(sharsnum,closep))
			self.ErasePattern()
	
	    
	def TryToEnterLong(self,closep):
		
		# try to enter long position	
		symbol=self.stockfeed.GetSymbolName()	
		hasTrade=False
		

		maxshare=self.position.GetMaxSharesCanBuy(symbol,closep)
		if self.position.EnterLong(symbol,closep,maxshare):
			print('buy %d of shares at %.2f$' %(maxshare,closep))
			
			self.tradedict['stoploss']=0.95*closep # set up  stop loss
			self.tradedict['cpoint']=closep			
			self.tradedict['stopwin']=self.waveindicator.GetPatternRetracmentTargetPrice(self.tradedict['curpattern'],self.tradedict['cpoint'])
			assert(self.tradedict['cpoint']<self.tradedict['stopwin'])
			hasTrade=True
					
		if hasTrade:
			profit=self.position.GetCurrentProfit()*100
			print('current profit is %.2f%%' %(profit))	
				
	def IsEnterLongOpportunity(self,closep):
		# track if current price meet the high probability trading needs
		
		if not self.tradedict['curpattern']: # not tracking any pattern  right now
			return False

		potentialend,patterndirection=self.waveindicator.IsPotentialPatternEnd(closep,self.tradedict['curpattern'])
		if potentialend>0 and patterndirection<0: # downtrend and reached target price
			return True
		elif potentialend<0:
			self.ErasePattern() # pattern is invalidated
			
	
		return False
		
				

	





def TestRun():


	m_stock=KSingleStock() # create its stock object
	m_stock.SetTick('us','nyse','bsx')	
	m_feed=KStockFeed(m_stock)
	m_stratgy=KStrategyCMiner(None,m_feed)
	m_stratgy.run()	
	print(m_stratgy.GetAllMetrics())



	
	return
	plt.figure()
	m_stratgy.sma1.plot()
	m_stratgy.stockfeed.GetDataFrame()['close'].plot()
	plt.show()

if __name__ == "__main__":
	useProfile=False	
	if useProfile:
		cProfile.run("TestRun()", "prof.txt")
		p = pstats.Stats("prof.txt")
		p.sort_stats("cumulative").print_stats()  

	else:
		TestRun()
